「ゾーンが一致しません」メッセージ
まとめ
Flutter 3.10 以降、フレームワークは不一致を検出します ゾーンを使用する場合、デバッグ ビルドでゾーンをコンソールに報告します。
バックグラウンド
ゾーンは、Dart でコールバックを管理するためのメカニズムです。
主にオーバーライドに役立ちますが、print
とTimer
テストのロジック、
テストでのエラーを見つけるために、
グローバル変数のスコープ設定に使用されることもあります
アプリケーションの特定の部分に。
Flutter には必要なものがあります (そしてこれまでも常に必要でした)
すべてのフレームワーク コードが同じゾーンで実行されるようにします。
特に、これは次の呼び出しを意味します。WidgetsFlutterBinding.ensureInitialized()
同じゾーンで実行する必要があります
への呼び出しとしてrunApp()
。
これまで、Flutter はそのような不一致を検出していませんでした。
これにより、不明瞭でデバッグが困難な問題が発生することがあります。
例えば、
キーボード入力のコールバックが呼び出される可能性があります
にアクセスできないゾーンを使用するzoneValues
それが期待していること。
私たちの経験では、
ゾーンを使用するすべてのコードではないにしても、ほとんどのコード
のすべての部分が保証されるわけではありません。
Flutter フレームワークは同じゾーンで動作しています
潜在的なバグがあります。
多くの場合、これらのバグはゾーンの使用とは無関係に見えます。
この不変条件に誤って違反した開発者を助けるために、 Flutter 3.10 以降、 不一致が検出された場合、デバッグ ビルドで致命的ではない警告が出力されます。 警告は次のようになります。
════════ Exception caught by Flutter framework ════════════════════════════════════
The following assertion was thrown during runApp:
Zone mismatch.
The Flutter bindings were initialized in a different zone than is now being used.
This will likely cause confusion and bugs as any zone-specific configuration will
inconsistently use the configuration of the original binding initialization zone or
this zone based on hard-to-predict factors such as which zone was active when a
particular callback was set.
It is important to use the same zone when calling `ensureInitialized` on the
binding as when calling `runApp` later.
To make this warning fatal, set BindingBase.debugZoneErrorsAreFatal to true before
the bindings are initialized (i.e. as the first statement in `void main() { }`).
[...]
═══════════════════════════════════════════════════════════════════════════════════
この警告は次のような場合に致命的になる可能性があります。
設定BindingBase.debugZoneErrorsAreFatal
にtrue
。
このフラグはデフォルトに変更される可能性があります。true
Flutter の将来のバージョンで。
移行ガイド
このメッセージを沈黙させる最善の方法は、 アプリケーション内からゾーンの使用を削除します。 ゾーンのデバッグは非常に難しい場合があります。 これらは本質的にグローバル変数であるため、 そしてカプセル化を破ります。 ベスト プラクティスは、グローバル変数とゾーンを避けることです。
ゾーンを削除できない場合
(たとえば、アプリケーションがサードパーティのライブラリに依存しているため)
構成がゾーンに依存している)、
次に、Flutter フレームワークへのさまざまな呼び出し
すべて同じゾーンに移動する必要があります。
通常、これは通話を次の場所に移動することを意味します。WidgetsFlutterBinding.ensureInitialized()
に
への呼び出しと同じクロージャrunApp()
。
これは、ゾーンが次の場合に厄介になる可能性があります。runApp
実行されます
で初期化されていますzoneValues
プラグインから取得した
(これには必要ですWidgetsFlutterBinding.ensureInitialized()
呼ばれたこと)。
この種のシナリオにおける 1 つのオプションは、
可変オブジェクトをzoneValues
、 と
値が利用可能になったら、そのオブジェクトをその値で更新します。
import 'dart:async';
import 'package:flutter/material.dart';
class Mutable<T> {
Mutable(this.value);
T value;
}
void main() {
var myValue = Mutable<double>(0.0);
Zone.current.fork(
zoneValues: {
'myKey': myValue,
}
).run(() {
WidgetsFlutterBinding.ensureInitialized();
var newValue = ...; // obtain value from plugin
myValue.value = newValue; // update value in Zone
runApp(...);
});
}
使用する必要があるコード内でmyKey
、
を使用して間接的に取得できますZone.current['myKey'].value
。
このような解決策がうまくいかない場合
サードパーティの依存関係により使用が必要となるため、
特定のタイプの、特定のzoneValues
鍵、
依存関係へのすべての呼び出しは、
包まれたZone
適切な値を提供する呼び出し。
この方法でゾーンを使用するパッケージを使用することを強くお勧めします。 より保守しやすいソリューションに移行します。
タイムライン
リリースされたバージョン: 3.9.0-9.0.pre
安定リリース: 3.10.0
参考文献
API ドキュメント:
Zone
BindingBase.debugZoneErrorsAreFatal
関連する問題:
- 問題 94123: Flutter フレームワークは、ensureInitialized の場合に警告を出しません runApp とは別のゾーンで呼び出されます
関連する PR:
- PR 122836: runApp が呼び出されることをアサートします binding.ensureInitialized と同じゾーン内